#pragma once

#include <direct.h> // for getcwd
#include <stdlib.h>// for MAX_PATH
#include <math.h>
#include <hash_set>
#include <algorithm>
#include <vector>
#include "SenetBoardDraft.h"
#include "CommonAlgorithmsDefs.h"
#include <assert.h>
// function to return the current working directory
// this is generally the application path
inline void getCurrentPath(char* buffer)
{
	getcwd(buffer, _MAX_PATH);
}

typedef enum SENET_EXCEPTION_ENUM_T
{

} SENET_EXCEPTION_ENUM;

inline float factorial (int num)
{
	float result=1.0f;
	for (int i = 1; i <= num; ++i)
	{
		result *= (float)i;
	}
	return result;
}

inline float getProbabilityStick(int stickNum, int totalSticks)
{
	float result = (factorial(totalSticks)) / ((factorial(stickNum) * factorial(totalSticks - stickNum)));
	result *= (float)(pow(0.5, totalSticks));
	return result;
}




class CommonApps
{
	public:
	static const int safeSeq = 2;		// Minimal length of a sequence from
										// which a piece cannot be removed
	static const int blockSeq = 3;		// Minimal length of a sequence that

	static inline bool hash_setContains(const stdext::hash_set<int>& hashmap, int val)
	{
		stdext::hash_set<int>::const_iterator iterObject = hashmap.find(val);
		return !(iterObject == hashmap.end());
	}

	static inline void sortVector(std::vector<int>& vec)
	{
		std::sort( vec.begin( ), vec.end( ) );
	}

	static inline void undoMoves(
		std::vector<SenetBoardDraftMove>& movesPerformed,
		SenetBoardDraft& board,
		Definitions::PlayerColor currentPlayer)
	{
		for(int i=movesPerformed.size()-1; i>=0 ; i--)
		{
			board.undoMove(movesPerformed[i].dest() , movesPerformed[i].start(), currentPlayer);
			// TODO: tal delete memory
		}
	}

	static inline float floatMax(float a, float b)
	{
		return (a > b ? a : b);
	}
	static inline float floatMin(float a, float b)
	{
		return (a < b ? a : b);
	}

	static NodeType getOppositeNodeType(NodeType nodeType)
	{
		assert(nodeType == MAX || nodeType == MIN);
		return nodeType == MAX ? MIN : MAX;
	}
	struct MoveHeuristicValue
	{
		int move;
		float heuristicScore;
		static bool BinarySortPredicate(const MoveHeuristicValue& d1, const MoveHeuristicValue& d2)
		{
			// > = ascending order
			// < = descending order
			return d1.heuristicScore > d2.heuristicScore;
		}
		static void SortAscMoveHeuristicVector(std::vector<MoveHeuristicValue>& vec)
		{
			std::sort(vec.begin(), vec.end(), BinarySortPredicate);

		}

	};
};